#include "hd_led.h"
#include "hd_ldr.h"
#include "delay.h"
#include "main.h"
#include "hd_oled.h"


void SystemClock_Config(void);

int main(void) {
    SystemClock_Config();

    // LED 初始化
    HD_LED_Init();
    // 光敏传感器
    HD_LDR_Init();
    // OLED 初始化
    HD_OLED_Init(OLED_SIZE_16, OLED_MODE_POSITIVE);
    HD_OLED_Full();
    HD_OLED_RefreshGram();
    delay_ms(1000);

    HD_OLED_Clear();
    HD_OLED_RefreshGram();
    delay_ms(1000);

    HD_OLED_ShowBinNum(0, 0, 0xCFE, 12);
    HD_OLED_ShowHexNum(104, 0, 0xCFE, 3);

    HD_OLED_ShowHexNum(0, 16, 0xA1B2D3, 6);

    HD_OLED_ShowSignedNum(0, 32, 123, 3);
    HD_OLED_ShowSignedNum(40, 32, -123, 3);
    HD_OLED_ShowFloatNum(80, 32, (float) 1.2, 3);

    HD_OLED_ShowString(0, 48, "ASCII:");
    HD_OLED_ShowString(64, 48, "CODE:");
    HD_OLED_RefreshGram();

    uint8_t keyNum;
    uint8_t c = ' ';
    while (1) {
        keyNum = HD_LDR_Level();
        if (keyNum == 1) {
            HD_LED_On();

            if (c++ > '~') c = ' ';

            HD_OLED_ShowChar(48, 48, c);
            HD_OLED_ShowNum(104, 48, c - ' ', 3);

#ifdef USE_FULL_OLED
            HD_OLED_SetMode(OLED_MODE_NEGATIVE);
            HD_OLED_SetSize(OLED_SIZE_24);
            HD_OLED_ShowChar(116, 16, c);

            HD_OLED_SetMode(OLED_MODE_POSITIVE);
            HD_OLED_SetSize(OLED_SIZE_12);
            HD_OLED_ShowNum(80, 16, c - ' ', 3);
            HD_OLED_ShowChar(104, 16, c);

            HD_OLED_SetSize(OLED_SIZE_16);
#endif
            HD_OLED_RefreshGram();

            delay_ms(1000);
        } else {
            HD_LED_Off();
        }
    }

}


/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void) {
    LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
    while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_4) {
    }
    LL_PWR_EnableRange1BoostMode();
    LL_RCC_HSE_Enable();
    /* Wait till HSE is ready */
    while (LL_RCC_HSE_IsReady() != 1) {
    }

    LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_6, 85, LL_RCC_PLLR_DIV_2);
    LL_RCC_PLL_EnableDomain_SYS();
    LL_RCC_PLL_Enable();
    /* Wait till PLL is ready */
    while (LL_RCC_PLL_IsReady() != 1) {
    }

    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
    /* Wait till System clock is ready */
    while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) {
    }

    /* Insure 1?s transition state at intermediate medium speed clock based on DWT */
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
    DWT->CYCCNT = 0;
    while (DWT->CYCCNT < 100);
    /* Set AHB prescaler*/
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
    LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
    LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);

    LL_Init1msTick(170000000);

    LL_SetSystemCoreClock(170000000);
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line) {
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
}

#endif /* USE_FULL_ASSERT */
